package com.alpha.processor.creators.binder_file;

import com.alpha.binder.interfaces.BinderInterface;
import com.alpha.binder.interfaces.ConnectorInterface;
import com.alpha.processor.creators.info_model.ConnectorInterfaceInfoModel;
import com.alpha.processor.processor.tools.ProcessorTool;
import com.alpha.processor.creators.base.FileCreator;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;

import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.util.Elements;

public class BinderFileCreator extends FileCreator {

    private final BinderCreateModel createModel;

    public BinderFileCreator(ProcessorTool logger, Elements elementUtils, TypeElement classElement) {
        createModel = new BinderCreateModel(logger,elementUtils,classElement);
    }

    @Override
    public String getFilePackageName() {
        return createModel.getPackageName();
    }

    @Override
    public String getGenerateFileName() {
        return createModel.getGenarateFileName();
    }

    @Override
    public String getGenerateFileFullName() {
        return createModel.getGenerateFileFullName();
    }

    @Override
    public Element getClassElement() {
        return createModel.getClassElement();
    }

    @Override
    protected void buildFile(TypeSpec.Builder fileBuilder) {
        fileBuilder.addModifiers(Modifier.PUBLIC);
        fileBuilder.addSuperinterface(BinderInterface.class);

        FieldSpec.Builder fieldBuilder = FieldSpec.builder(ClassName.bestGuess(createModel.getGenerateFileFullName()),
                BinderCreateModel.ParamName);
        fieldBuilder.addModifiers(Modifier.PUBLIC);
        fieldBuilder.addModifiers(Modifier.STATIC);
        fieldBuilder.addModifiers(Modifier.FINAL);
        fieldBuilder.initializer("new $T()",ClassName.bestGuess(createModel.getGenerateFileFullName()));
        fileBuilder.addField(fieldBuilder.build());

        fileBuilder.addMethod(generateBindDataMethod());
    }

    // Implement Method --- bindData
    private MethodSpec generateBindDataMethod() {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(BinderCreateModel.MethodName)
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .addParameter(String.class, "className")
                .returns(ClassName.bestGuess(createModel.getConnectorInfoModel().getInterfaceName()));

        methodBuilder.addCode("switch(className){\n");
        for (String targetClassName:createModel.getGenerateClassMap().keySet()){
            methodBuilder.addCode("\tcase \"" + targetClassName + "\":\n");
            methodBuilder.addCode("\t\treturn new $T();\n",ClassName.bestGuess(createModel.getGenerateClassMap().get(targetClassName)));
        }
        methodBuilder.addCode("\tdefault:\n");
        methodBuilder.addCode("\t\treturn null;\n");
        methodBuilder.addCode("}\n");
        return methodBuilder.build();
    }

    public BinderCreateModel getCreateModel() {
        return createModel;
    }
}
